home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
011
/
adikit.arc
/
DSHERC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1986-12-01
|
21KB
|
619 lines
/* DSHERC.C
Sample ADI device driver for use as model in driver development.
Configurator and display driver for the Hercules display board on
the IBM PC. Split-screen configuration.
*/
/* #define DEBUG 1 */
/* If DUMB is defined, this driver will act as a very stupid display
and make AutoCAD do all its tricks to restore things on mode
switches. */
/* #define DUMB 1 */
/* If SMART is defined, this driver will include test code to exercise
the "extended functions" SYNC and REDRAW. It doesn't really do them.
It is imprudent to set both SMART and DUMB at the same time. */
/* #define SMART 1 */
#include <stdio.h>
#define VERSION "1.10"
#define REVDATE "10/28/86"
#define FALSE 0
#define TRUE 1
/* Default interrupt vector for display drivers is 0x7A. This is
selectable by user during AutoCAD configuration. */
#define VECTOR 0x7A /* Interrupt vector used for messages */
#define YSIZE 348
#define XSIZE 720
#define BASE6845 0x3B4 /* CRT controller base address. */
#define ADRREG BASE6845
#define DATAREG (BASE6845+1)
#define CTLREG (BASE6845+4)
#define STATREG (BASE6845+6)
#define CFGREG (BASE6845+11) /* configuration register */
#define INITL 14 /* Number of CRTC regs to initialize. */
#define NSYNC 6 /* Number of vsyncs to wait on mode switch */
#define TEXTSEG 0xB000 /* vram base for text screen. */
#define MCHARS 8 /* Characters in a menu box. */
#define CHARHGT 14 /* Character height in pixels. */
#define CHARWID 9 /* Character width. */
#define XMENUMIN (XSIZE-CHARWID*MCHARS) /* Left margin of menu box. */
#define XMAX (XMENUMIN-6) /* Right margin of graphics area. */
#define SPLIT 3 /* Lines in split-text area. */
#define SPLITHGT (CHARHGT*SPLIT+7) /* Split-text area height. */
#define YSPLIT (YSIZE-SPLIT*CHARHGT) /* Row nr of text area */
#define XCLINE (9*40) /* Start of coordinate display line. */
#define msb(v) ((v >> 8) & 0xFF)
#define lsb(v) (v & 0xFF)
#define packbyte(x, y) ((x << 8) | y)
/* BIOS interrupt numbers and subfunctions: */
#define VIDEO_IO 0x10
#define SCURSOR 2 /* Set cursor */
#define SCROLL_UP 6 /* Scroll active page up */
/* Request codes */
#define INIT1 1 /* Initialise parameters 1 */
#define INIT2 2 /* Initialise parameters 2 */
#define INIT3 3 /* Initialise parameters 3 */
#define INIT4 4 /* Initialise parameters 4 */
#define INIT5 5 /* Initialise parameters 5 */
#define TERM 9 /* Terminate */
#define CLEAR 10 /* Clear graphics screen */
#define DOT 11 /* Complement dot */
#define MOVE 12 /* Set screen cursor */
#define DRAW 13 /* Draw line */
#define FLOOD 14 /* Solid fill vertex / point */
#define MARK 15 /* Draw graphic cursor */
#define CMARK 16 /* Clear graphic cursor */
#define CHAR 20 /* Draw character on graphics screen */
#define ECHAR 21 /* End character string */
#define MHLITE 22 /* Menu highlight */
#define MDHLITE 23 /* Menu de-highlight */
#define MNUCUR 24 /* Set character address to box */
#define TPROMPT 30 /* Set character address to prompt line */
#define QPLOT 31 /* Screen dump */
#define RPEN 32 /* Read pen */
#define GOTEXT 33 /* Go to text screen */
#define GOTEXTU 34 /* Go to text screen - user request */
#define GOGRAPH 35 /* Go to graphics screen */
#define WRSPLIT 36 /* Write to split screen */
#define MODELINE 37 /* Write to mode line */
#define COORDL 38 /* Write to coordinate line */
#define SYNC 50 /* Flush display buffers */
#define REDRAW 51 /* Driver-local redraw */
/* Configuration bits */
#define CF_TEXT 1 /* Draw text scrolling area */
#define CF_MENU 2 /* Draw screen menu */
#define CF_STATUS 4 /* Draw status line */
/* Repaint control bits */
#define RP_STAT 1 /* Repaint status line */
#define RP_MENU 2 /* Repaint status line */
#define RP_SCROLL 4 /* Repaint scroll area */
#define RP_GRAPH 8 /* Redraw picture */
/* Driver mode bits */
#define DM_CCECH 1 /* Suppress echo of control C */
#define DM_HLEN 2 /* Driver can do highlighting */
#define DM_GROK 4 /* Driver is single screen */
/* Extended function enable bits */
#define EF_SYNC 1 /* Enable SYNC function */
#define EF_REDRAW 2 /* Enable REDRAW function */
/****** Global symbols exported (to DSHERCA) ******/
short graphx, graphy; /* Graphics area width and height. */
short color; /* Current colour */
short hilight; /* Highlight flag */
short cline; /* Status line configured */
/****** Local stuff ******/
/* Initial values for CRTC registers R0-R13 */
static char
graphinit[INITL] = {
56,45,48, 8,90,0,87,87,2, 3, 0, 0,0,0}
,
textinit[INITL] = {
97,80,82,15,25,6,25,25,2,13,0,14,0,0};
static short tcursx,tcursy; /* Text cursor position */
static int splitchar = 0, /* Characters in current line. */
splitline = YSPLIT, /* Line we're writing on. */
splitdirty = 0;/* Any characters on line flag. */
static short ybias; /* To convert shorts to hard coords. */
static short notxt, nomnu; /* Configuration status */
static short ixdots, iydots, ixdotsm, modelinl, mnuchars,
maxboxes, hlenab, graphok, hwfill;
struct pregs { /* Structure to communicate with ACAD */
short code, arg1, arg2, arg3;
};
static struct pregs c; /* Master communication structure */
extern char inp();
unsigned r6845();
extern long _psp, _mnext;
extern unsigned _tsize;
main(argc,argv)
int argc;
char *argv[];
{
short i, cl;
short lx, ly;
#ifdef DEBUG
printf("\n Mnext = %08lx _Psp = %08lx _tsize = %04x",
_mnext, _psp, _tsize);
#endif
printf("\n--- Autodesk Device Interface/ADI Driver ---");
#ifdef DUMB
printf("\nDumb ADI graphics board driver Vers. %s installed as INT %03xh.",
#else
printf("\nHercules Graphics Board driver Vers. %s installed as INT %03xh.",
#endif
VERSION,VECTOR);
#ifdef SMART
printf("\nSmart display debugging features enabled.");
#endif
printf("\nSample ADI Driver created %s by Autodesk, Inc.\n",REVDATE);
/* ADI driver developer should include name of company, or company and
individual, responsible for creation of ADI device driver and date
of driver creation to aid in identifying driver. */
while (TRUE) {
iwait(VECTOR, &c, &c);
/* Dispatch commands received from active program */
#ifdef DUMPCMD
if (c.code != 32) { /* Skip pen probes */
if (c.code == 20 || c.code == 36)
putchar(c.arg1);
else
printf("\n ** Display(%d): %d, %d, %d **",
c.code, c.arg1, c.arg2, c.arg3);
}
#endif
switch (c.code) {
case INIT1:
notxt = !(c.arg1 & CF_TEXT);
nomnu = !(c.arg1 & CF_MENU);
cline = !!(c.arg1 & CF_STATUS);
ixdotsm = XSIZE - 1;
ixdots = nomnu ? XSIZE - 1 : XMAX;
graphx = (ixdots + 1); /* Graphics area width. */
/* YBIAS: "natural" y-coordinate of screen coord origin. Also
number of pixels vertically in menu area. */
ybias = iydots = notxt ? YSIZE - 1 : YSIZE - 1 - SPLITHGT;
if (cline)
iydots -= CHARHGT; /* Status line correction. */
modelinl = XCLINE/9; /* Mode line length. */
graphy = iydots + 1; /* Graphics area height. */
mnuchars = MCHARS;
maxboxes = nomnu ? 0 : (ybias+1) / CHARHGT;
hwfill = 0; /* No hardware fill */
hlenab = 1; /* Driver knows how to highlight */
graphok = 1; /* Graphics mode ok now. */
c.code = TRUE;
c.arg1 = ixdots;
c.arg2 = iydots;
c.arg3 = ixdotsm;
break;
case INIT2:
c.arg1 = packbyte(modelinl, mnuchars);
#ifdef DUMB
c.arg2 = packbyte(maxboxes, DM_HLEN | DM_GROK | DM_CCECH);
#else
c.arg2 = packbyte(maxboxes, DM_HLEN | DM_GROK);
#endif
c.arg3 = packbyte(SPLIT, hwfill);
break;
case INIT3:
#ifdef DEBUG
printf("\nINIT3: notxt %d nomnu %d cline %d ixdots %d iydots %d",
notxt, nomnu, cline, ixdots, iydots);
printf("\n graphx %d graphy %d ybias %d modelinl %d",
graphx, graphy, ybias, modelinl);
printf("\n mnuchars %d maxboxes %d hwfill %d hlenab %d",
mnuchars, maxboxes, hwfill, hlenab);
printf("\n graphok %d\n", graphok);
#endif
outp(CFGREG,3); /* Enable graphics mode, page1 */
adswipe(); /* Clear the (invisible) graphics screen */
gograph(); /* Go to graphics mode. */
drawbord(); /* Draw the borders */
c.arg1 = 5556; /* X pixel spacing */
c.arg2 = 8621; /* Y pixel spacing */
#ifdef DUMB
c.arg3 = packbytes(25, 80);
#else
c.arg3 = 0;
#endif
break;
case INIT4:
c.arg1 = 0; /* No extended functions */
#ifdef SMART
c.arg2 = EF_SYNC | EF_REDRAW;
#else
c.arg2 = 0; /* for now, thanks */
#endif
break;
case INIT5:
c.arg1 = iydots; /* Ymenumax = iydots */
c.arg2 = YSIZE - 1; /* iydotsm */
break;
case TERM:
break;
case CLEAR:
#ifdef DUMB
adswipe();
drawbord();
c.arg1 = RP_MENU | RP_STAT | RP_SCROLL;
#else
adsclr();
c.arg1 = 0;
#endif
break;
case DOT:
adsdot(c.arg1, ybias - c.arg2);
break;
case MOVE:
lx = c.arg1;
ly = c.arg2;
hilight = c.arg3 & 1;
break;
case DRAW:
#ifdef DUMPCMD
printf("\nDraw (%d,%d) - (%d,%d) in %d",
lx, ly, c.arg1, c.arg2, c.arg3);
#endif
if (c.arg3 >= 0) {
color = c.arg3;
adsvec(lx, ybias - ly, c.arg1, ybias - c.arg2);
}
else
adsxvec(lx, ybias - ly, c.arg1, ybias - c.arg2);
break;
case FLOOD:
break;
case MARK:
case CMARK:
if (c.arg3 == 0 || c.arg3 == 3) {
adsmark(c.arg1, ybias - c.arg2);
c.code = TRUE;
}
else
c.code = FALSE;
break;
case CHAR:
if (tcursx <= (XSIZE-CHARWID))
adschar(tcursx, tcursy, c.arg1);
tcursx += CHARWID;
break;
case ECHAR:
break;
case MHLITE:
case MDHLITE:
for (i = 0, cl = tcursx; i < MCHARS; i++) {
dsrvid(cl, tcursy); /* Invert all the characters. */
cl += CHARWID;
}
c.arg1 = FALSE; /* Say characters not needed */
break;
case MNUCUR:
i = (ybias + 1) / c.arg2;
tcursx = XMENUMIN;
tcursy = (ybias + 1 - CHARHGT) - (c.arg2 - c.arg1 - 1) * i;
break;
case TPROMPT:
break;
case QPLOT:
break;
case RPEN:
c.arg1 = 0;
break;
case GOTEXT:
gotext();
break;
case GOTEXTU:
gotextu();
#ifdef DUMB
txclr();
#endif
break;
case GOGRAPH:
gograph();
#ifdef DUMB
adswipe();
c.arg1 = RP_GRAPH | RP_MENU | RP_STAT | RP_SCROLL;
#else
c.arg1 = 0;
#endif
break;
case WRSPLIT:
wrsplit(c.arg1);
break;
case MODELINE:
tcursx = tcursy = 0;
adschar(tcursx, tcursy, 'C');
tcursx += CHARWID;
adschar(tcursx, tcursy, c.arg2 + '0'); /* Colour */
tcursx += CHARWID;
adschar(tcursx, tcursy, ' ');
tcursx += CHARWID;
break;
case COORDL:
tcursx = XCLINE;
tcursy = 0;
break;
#ifdef SMART
case SYNC:
printf(" <sync> ");
break;
case REDRAW:
printf(c.arg1 ? " <clear> " : " <redraw> ");
c.code = FALSE;
break;
#endif
default:
printf("\n** Unimplemented display command code %d **\n",
c.code);
c.code = FALSE;
}
}
}
static gograph()
{
int cursor, splitbase, i;
char rch;
modeinit(0x82, graphinit);/* Put the CRTC in graphics mode. */
if (notxt) /* Graphics text configured off? */
return;
/* Copy the bottom SPLIT lines on the text screen into the text
area of the graphics screen. Start by finding address within
text screen buffer of first character to copy (note that the
text buffer has two bytes per displayed character). */
cursor = r6845(14) << 1; /* Cursor address from CRTC. */
splitbase = cursor - cursor%160 - ((SPLIT-1)*160);
if (splitbase < 0) splitbase = 0;
clearsplit(); /* Clear text area on graphics screen. */
#ifndef DUMB
for (i = splitbase; i < cursor; i += 2) { /* Read character from */
peek(TEXTSEG, i, &rch, 1);
wrsplit1(rch); /* text screen, copy to graphics. */
}
#endif
}
/* Go into text mode if not already there, with a clear screen. */
static gotext()
{
txclr();
gotextu(); /* Switch modes. */
}
/* Go into text mode at user request (show hidden text). */
static gotextu()
{
modeinit(0, textinit); /* Make the mode switch. */
}
/* Write a character to the graphics screen text area and save it in
in "hidden" text. */
static wrsplit(c)
char c;
{
wrsplit1(c);
#ifndef DUMB
putchar(c); /* Let OS write to hidden screen. */
#endif
}
/* Write a character to the graphics screen text area. */
static wrsplit1(c)
char c;
{
if (notxt)
return; /* No graphics text area. */
switch (c) {
case '\r': /* Carriage return */
splitchar = 0;
break;
case '\n': /* Line feed. */
if (splitdirty) /* Unless current line is blank, */
{
splitline += CHARHGT; /* advance to next. */
splitdirty = 0;
}
break;
case '\t': /* tab (does better than DOS!) */
do
wrsplit1(' ');
while (splitchar & 7);
break;
case '\b': /* backspace. */
if (splitchar > 0)
splitchar -= CHARWID;
break;
default: /* Normal character. */
if (splitchar >= XSIZE) /* If off end of line, */
{
wrsplit1('\r'); /* do a line feed. */
wrsplit1('\n');
}
adschar(splitchar, splitline, c); /* Draw it. */
splitchar += CHARWID; /* Update cursor. */
splitdirty = 1; /* Non-blank line. */
}
if (splitline >= YSIZE) /* If off bottom of screen, */
{
hcscroll(SPLIT); /* scroll up. */
splitline -= CHARHGT;
}
}
/* Initialize the CRTC in a new mode. ctlbits is the value to be
put into the CRT control register, and should not include the
enable-video bit. */
static modeinit(ctlbits, initstr)
char ctlbits, *initstr;
{
int i;
outp(CTLREG, ctlbits); /* Disable video signal. */
for (i = 0; i < INITL; i++) /* Load 6845 registers. */
{
outp(ADRREG, i); /* Point to reg. #i */
outp(DATAREG, *initstr++); /* Send it its value. */
}
for (i = -1; ++i < NSYNC; ) /* Wait until vertical sync */
{
while (~inp(STATREG) & 0x80) ; /* goes low for the */
while (inp(STATREG) & 0x80) ; /* NSYNCHth time */
}
outp(CTLREG, ctlbits | 8);/* to re-enable video. */
}
/* Routine to read a 16-bit CRTC register. */
static unsigned int r6845(r)
int r;
{
char r1, r0;
outp(ADRREG, r++); /* Point to the register. */
r1 = inp(DATAREG); /* Read high byte. */
outp(ADRREG, r); /* Point to next register. */
r0 = inp(DATAREG); /* Read low byte. */
return (unsigned int)r0 | ((unsigned int)r1 << 8); /* Return both. */
}
/* TXCLR -- Clear the text screen */
static txclr()
{
/* Call BIOS to scroll screen clear. */
ibmbios(VIDEO_IO, SCROLL_UP, 0, 0x184F, 0, 0x700);
/* Now have it set the cursor to upper left corner. */
ibmbios(VIDEO_IO, SCURSOR, 0, 0, 0, 0);
}
/* DRAWBORD -- Draw borders on graphics screen */
static drawbord()
{
short i;
/* Draw the borders */
color = 7;
if (!notxt)
for (i = 0; i-- > -2; ) /* Horizontal */
adsvec(0, ybias - i, ixdotsm, ybias - i);
if (!nomnu)
for (i = XMAX; i++ < (XMAX + 2); ) /* Vertical */
adsvec(i, ybias, i, 0);
}
/* Clear the graphics text area and reset its insertion cursor. */
static clearsplit()
{
int i;
#ifndef DUMB
for (i=0; i<SPLIT; i++) /* All these scrolls will */
hcscroll(SPLIT); /* clear the area. */
#endif
/* Set insertion cursor to SPLIT lines above screen bottom */
splitchar = 0;
splitline = YSPLIT;
}